package Game;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

public class SpeciesLife extends Thread{
	public static Position[][] BATTLEFIELD = Core.getBATTLEFIELD();
	//volatile ArrayList <Ant> ants;
	private boolean isReady = true;
	Species species;
	public boolean isReady() {
		return isReady;
	}


	private void setReady(boolean isReady) {
		this.isReady = isReady;
	}


	SpeciesLife(Species species) {
		this.species = species;
	}
	
	
	public synchronized void run() {
		while(true) {
			setReady(false);
			List <Ant>  ants = null;
			if(species == Species.BLACK) {
				synchronized(Core.antsBlack) {
					ants = Collections.synchronizedList(Core.antsBlack);
				}
			} else if(species == Species.RED){
				synchronized(Core.antsRed) {	
					ants =  Collections.synchronizedList(Core.antsRed);
				}
			} else if(species == Species.YELLOW) {
				synchronized(Core.antsYellow) {
					ants =  Collections.synchronizedList(Core.antsYellow);
				}
			} else if(species == Species.GREEN) {
				synchronized(Core.antsGreen) {
					ants =  Collections.synchronizedList(Core.antsGreen);
				}
			}
			
			synchronized(ants){
				//Iterator<Ant> it = ants.iterator();

					for(int i = 0; i<ants.size(); i++ ) {
						Ant ant = ants.get(i);
						ant.makeOlder();
					ArrayList<Ant> niegbhours = getNeighbours(ant);
					if(fight(ant, niegbhours)) {
						//System.out.println("Walcze");
					} else if(moving(ant)){
						//System.out.println("Rozmnazam");
					} else {
						multiply(ant, niegbhours);
						
						
					}
					try {
						this.sleep(Settings.LIFE_SPEED);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					}
				}
			
			
			try {
				setReady(true);
				////System.out.println("zasnalem");
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}



	private ArrayList<Ant> getNeighbours(Ant ant) {
		ArrayList<Ant> neighbours = new ArrayList<Ant>();
		int x = ant.getX();
		int y = ant.getY();

		if(x-1>=0 && !BATTLEFIELD[x-1][y].isBlank()) {
			neighbours.add(BATTLEFIELD[x-1][y].getAnt());
		}
		
		if(x-1>=0 && y-1>=0 && !BATTLEFIELD[x-1][y-1].isBlank()) {
			neighbours.add(BATTLEFIELD[x-1][y-1].getAnt());
		}
		
		if(y-1>=0 && !BATTLEFIELD[x][y-1].isBlank()) {
			neighbours.add(BATTLEFIELD[x][y-1].getAnt());
		}
		
		if(x+1<Settings.bfSize && y-1>=0 && !BATTLEFIELD[x+1][y-1].isBlank()) {
			neighbours.add(BATTLEFIELD[x+1][y-1].getAnt());
		}
		
		if(x+1<Settings.bfSize && !BATTLEFIELD[x+1][y].isBlank()) {
			neighbours.add(BATTLEFIELD[x+1][y].getAnt());
		}
		
		if(x+1<Settings.bfSize &&  y+1<Settings.bfSize && !BATTLEFIELD[x+1][y+1].isBlank()) {
			neighbours.add(BATTLEFIELD[x+1][y+1].getAnt());
		}
		
		if(y+1<Settings.bfSize && !BATTLEFIELD[x][y+1].isBlank()) {
			neighbours.add(BATTLEFIELD[x][y+1].getAnt());
		}
		
		if(x-1>=0 && y+1<Settings.bfSize && !BATTLEFIELD[x-1][y+1].isBlank()) {
			neighbours.add(BATTLEFIELD[x-1][y+1].getAnt());
		}
		
		return neighbours;
	}


	private boolean fight(Ant ant, ArrayList<Ant> niegbhours) {
		if(niegbhours.isEmpty()) {
			return false;
		}
		Iterator<Ant> it = niegbhours.iterator();
		boolean wasFight = false;
		if(it == null){
			return false;
		}

				while(it.hasNext()) {
					Ant antN = it.next();
					if(antN != null) {
					synchronized(ant) {
						synchronized(antN) {

							if(antN.getSpecies() != ant.getSpecies()) {
								fightEngine(antN,ant);
								wasFight = true;
							}
						}
					}
					}
			
		}
			   
			  //  //System.out.println("atak m2 " + antN);
		return wasFight;

		
	}
	
	private synchronized void  fightEngine(Ant antN, Ant ant) {

		synchronized(ant) {
			synchronized(antN) {
				int sAnt = ant.getStrength();
				int expAnt = ant.getExpirence();
				int sizeAnt = ant.getSize();

				
				int sAntn = antN.getStrength();
				int expAntn = antN.getExpirence();
				int sizeAntn = antN.getSize();

				
				while(true) {
					
				    int m1s1 = new Random().nextInt(expAnt)+1;
				    int m2s1 = new Random().nextInt(expAntn)+1;
				    
				    int m1s2 = new Random().nextInt(sizeAnt + sAnt)+1;
				    int m2s2 = new Random().nextInt(sizeAntn + sAntn)+1;
				    
				    int attackValueM1 = m1s1*m1s2;
				    int attackValueM2 = m2s1*m2s2;

				    
				    if(new Random().nextBoolean()) {
				    	ant.hurt(attackValueM2);
				    }
				   // //System.out.println("Zycie m1 " + ant.getHp());
				    if(ant.getHp()<0) {
				    	antN.growExperience();
				    	break;
				    } 
				    
				    if(new Random().nextBoolean()) {
				    	antN.hurt(attackValueM1);
				    }
				  //  //System.out.println("Zycie m2 " + antN.getHp());
				    if(antN.getHp()<0){
				    	ant.growExperience();
				    	break;
				    }
				}
				
				
				
			}
		}
		
	}


	private boolean moving(Ant ant) {

		synchronized(ant) {
				 int x = ant.getX();
				 int y = ant.getY();
				 int counter = 0;
				 boolean doYouWantGo = new Random().nextBoolean();
				 boolean moved = false;
				 if (doYouWantGo) {					 
					 while(!moved) {
					 int direction = new Random().nextInt(Settings.PROPABILITY_MOVING);
						if(counter++==100) {							
							return false;
						}

					 	switch(direction) {
					 	
					 	case 0: if(x-1>=0 && BATTLEFIELD[x-1][y].isBlank()) {
					 			
					 			ant.move(x-1, y);
					 			moved = true;
					 			
							}
					 	break;	
					 	case 1:	if(x-1>=0 && y-1>=0 && BATTLEFIELD[x-1][y-1].isBlank()) {
					 			ant.move(x-1, y-1);
					 			moved = true;
					 			
							}
					 	break;
					 	case 2:	if(y-1>=0 && BATTLEFIELD[x][y-1].isBlank()) {
					 			ant.move(x, y-1);
					 			moved = true;	
					 		
							}
						break;	
					 	case 3:	if(x+1<Settings.bfSize && y-1>=0 && BATTLEFIELD[x+1][y-1].isBlank()) {
					 			ant.move(x+1, y-1);
					 			moved = true;			
					 		 	
							}
						break;	
					 	case 4:	if(x+1<Settings.bfSize && BATTLEFIELD[x+1][y].isBlank()) {
					 			ant.move(x+1, y);
					 			moved= true;
					 		 		
							}
					 	break;	
					 	case 5:	if(x+1<Settings.bfSize &&  y+1<Settings.bfSize && BATTLEFIELD[x+1][y+1].isBlank()) {
					 			ant.move(x+1, y+1);
					 			moved= true;	
					 		
							}
						break;		
					 	case 6:	if(y+1<Settings.bfSize && BATTLEFIELD[x][y+1].isBlank()) {
					 			ant.move(x, y+1);
					 			moved= true;		
					 			
							}
					 	break;		
					 	case 7:	if(x-1>=0 && y+1<Settings.bfSize && BATTLEFIELD[x-1][y+1].isBlank()) {

					 			ant.move(x-1, y+1);
					 			moved= true;			
					 		 	
							}
						break;
					 	default: //if(x-1>=0&&y-1>=0) //System.out.println(direction + " Nie mam gdzie isc " + ant.getX() + " " + ant.getY() + BATTLEFIELD[ant.getX()-1][ant.getY()-1].isBlank()); 
					 			break;
					 	}
					 }	
				 } else {
					 return false;
				 }
		}
		
		return true;

		
	}

	private boolean multiply(Ant ant, ArrayList<Ant> niegbhours) {
		 
		if(niegbhours.isEmpty()) {
			
			return false;
		}

		Iterator<Ant> it = niegbhours.iterator();

		
		if(it == null){
			return false;
		}

		
		while(it.hasNext()) {
			Ant antN = it.next();
			if(antN!=null) {
				synchronized(ant) {
					synchronized(antN) {
					if(antN.getGenre() != ant.getGenre() 
							&& antN.getSpecies() == ant.getSpecies()
							&& antN.getAge()>Settings.minMultiplyAge && ant.getAge()>Settings.minMultiplyAge) {
						
						multiplyEngine(antN,ant);
						return true;
					}
					}
				}
			}
		}
		
		return false;
		
	}


	private void multiplyEngine(Ant antN, Ant ant) {
		synchronized(ant) {
			synchronized(antN) {
				 int baby = new Random().nextInt(Settings.PROPABILITY_CHILD);
				if(baby==2) {
					Species species = ant.getSpecies();
					Ant babyAnt = new Ant(species);
					BATTLEFIELD[babyAnt.getX()][babyAnt.getY()].setAnt(babyAnt);
					
					if(species == Species.BLACK) {
						synchronized(Core.antsBlack){
							Core.antsBlack.add(babyAnt);
						}
					} else if(species == Species.RED){
						synchronized(Core.antsRed) {
							Core.antsRed.add(babyAnt);
						}
					} else if(species == Species.YELLOW) {
						synchronized(Core.antsYellow) {
							Core.antsYellow.add(babyAnt);
						}
					} else if(species == Species.GREEN) {
						synchronized(Core.antsGreen) {
							Core.antsGreen.add(babyAnt);
						}
					}
					
				}
				
			}
		}
		
	}


}
